#include "comunicacao_servidor.h"

int executa_sistema_servidor(int sockfd){
  int i;
  request req;
  struct sockaddr_in to;
  socklen_t tolen;
  FILE *fp = NULL;

  tolen = sizeof(to);
  if(read_request(sockfd, &req, 0, (struct sockaddr *)&to, &tolen)<0)
    return -1;

#ifdef MARCAR_TEMPOS_SERVIDOR
  gettimeofday(&t0_servidor, NULL);

  /* Seleciona o arquivo correto para gravar o
     tempo de acordo com a porta do cliente */
  for(i=0; i<NUM_CLIENTES; i++){
    if(portas[i]==to.sin_port){
      fp = fp_tempos_servidor[i];
      break;
    }else if(portas[i]==0){
      fp = fp_tempos_servidor[i];
      portas[i] = to.sin_port;
      break;
    }
  }

#endif

  printf("Recebi opt = %c, id = %d, nota = %d\n", req.opt, req.id, req.nota);

  /* Testa se o pedido recebido e' valido */
  if(req.opt>='1' && req.opt<='6'){

    /* Seleciona opcao correta */
    switch(req.opt){
    case '1':
      if(enviar_titulos(sockfd, (struct sockaddr *)&to, tolen)<0)
	return -1;
      break;
    case '2':
      if(enviar_sinopse_filme(sockfd, req.id, (struct sockaddr *)&to, tolen)<0)
	return -1;
      break;
    case '3':
      if(enviar_informacoes_filme(sockfd, req.id, (struct sockaddr *)&to, tolen)<0)
	return -1;
      break;
    case '4':
      if(enviar_tudo(sockfd, (struct sockaddr *)&to, tolen)<0)
	return -1;
      break;
    case '5':
      if(enviar_confirmacao_nota(sockfd, req.id, req.nota, (struct sockaddr *)&to, tolen)<0)
	return -1;
      break;
    case '6':
      if(enviar_nota_filme(sockfd, req.id, (struct sockaddr *)&to, tolen)<0)
	return -1;
      break;
    }

#ifdef MARCAR_TEMPOS_SERVIDOR
    /* Salva o tempo medido em um arquivo */
    if(fp)
      fprintf(fp, "%lf;\n", t1_servidor.tv_sec-t0_servidor.tv_sec+(t1_servidor.tv_usec-t0_servidor.tv_usec)/(double)1000000);
#endif

  }

  return 0;
}

int enviar_titulos(int sockfd, struct sockaddr *to, socklen_t tolen){
  int i;
  tFilme filme[MAX_FILMES];
  /* Carrega as informacoes */
  for(i=0; i<idAtual; i++)
    filme[i] = carregar_informacoes_filme(i);

#ifdef MARCAR_TEMPOS_SERVIDOR
  gettimeofday(&t1_servidor, NULL);
#endif

  /* Envia titulos */
  if(write_int(sockfd, idAtual, to, tolen)<0)
    return -1;
  for(i=0; i<idAtual; i++)
    if(write_string(sockfd, filme[i].titulo, TAM_MAX_TITULO, to, tolen)<0)
      return -1;

  return 0;
}

int enviar_sinopse_filme(int sockfd, int idfilme, struct sockaddr *to, socklen_t tolen){
  tFilme filme;
  if(idfilme<0 || idfilme>=idAtual)
    idfilme = 0;
  filme = carregar_informacoes_filme(idfilme);
#ifdef MARCAR_TEMPOS_SERVIDOR
  gettimeofday(&t1_servidor, NULL);
#endif
  if(write_string(sockfd, filme.sinopse, TAM_MAX_SINOPSE, to, tolen)<0)
    return -1;
  return 0;
}

int enviar_informacoes_filme(int sockfd, int idfilme, struct sockaddr *to, socklen_t tolen){
  tFilme filme;
  if(idfilme<0 || idfilme>=idAtual)
    idfilme = 0;
  filme = carregar_informacoes_filme(idfilme);
#ifdef MARCAR_TEMPOS_SERVIDOR
  gettimeofday(&t1_servidor, NULL);
#endif
  if(write_string(sockfd, filme.titulo, TAM_MAX_TITULO, to, tolen)<0)
    return -1;
  if(write_string(sockfd, filme.horario, TAM_MAX_HORARIO, to, tolen)<0)
    return -1;
  if(write_int(sockfd, filme.sala, to, tolen)<0)
    return -1;
  if(write_string(sockfd, filme.sinopse, TAM_MAX_SINOPSE, to, tolen)<0)
    return -1;
  if(write_int(sockfd, filme.nota, to, tolen)<0)
    return -1;
  if(write_int(sockfd, filme.numClientes, to, tolen)<0)
    return -1;

  return 0;
}

int enviar_tudo(int sockfd, struct sockaddr *to, socklen_t tolen){
  int i;
  tFilme filme[MAX_FILMES];
  /* Carrega as informacoes */
  for(i=0; i<idAtual; i++)
    filme[i] = carregar_informacoes_filme(i);

#ifdef MARCAR_TEMPOS_SERVIDOR
  gettimeofday(&t1_servidor, NULL);
#endif

  /* Envia os dados pedidos */
  if(write_int(sockfd, idAtual, to, tolen)<0)
    return -1;
  for(i=0; i<idAtual; i++){
    if(write_string(sockfd, filme[i].titulo, TAM_MAX_TITULO, to, tolen)<0)
      return -1;
    if(write_string(sockfd, filme[i].horario, TAM_MAX_HORARIO, to, tolen)<0)
      return -1;
    if(write_int(sockfd, filme[i].sala, to, tolen)<0)
      return -1;
    if(write_string(sockfd, filme[i].sinopse, TAM_MAX_SINOPSE, to, tolen)<0)
      return -1;
    if(write_int(sockfd, filme[i].nota, to, tolen)<0)
      return -1;
    if(write_int(sockfd, filme[i].numClientes, to, tolen)<0)
      return -1;
  }

  return 0;
}

int enviar_confirmacao_nota(int sockfd, int idfilme, int nota, struct sockaddr *to, socklen_t tolen){
  tFilme filme;

  if(idfilme<0 || idfilme>=idAtual)
    idfilme = 0;

  /* Salva nova nota */
  filme = carregar_informacoes_filme(idfilme);
  filme.nota = (filme.nota*filme.numClientes+nota)/(++filme.numClientes);
  salvar_informacoes_filme(&filme);

#ifdef MARCAR_TEMPOS_SERVIDOR
  gettimeofday(&t1_servidor, NULL);
#endif

  if(write_int(sockfd, idfilme, to, tolen)<0)
    return -1;

  return 0;
}

int enviar_nota_filme(int sockfd, int idfilme, struct sockaddr *to, socklen_t tolen){
  tFilme filme;

  if(idfilme<0 || idfilme>=idAtual)
    idfilme = 0;

  filme = carregar_informacoes_filme(idfilme);

#ifdef MARCAR_TEMPOS_SERVIDOR
  gettimeofday(&t1_servidor, NULL);
#endif

  if(write_int(sockfd, filme.nota, to, tolen)<0)
    return -1;
  if(write_int(sockfd, filme.numClientes, to, tolen)<0)
    return -1;

  return 0;

}
